/**
 * Copyright (C)  2011  chen wei hua.
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 2.0
 * or any later version published by the Free Software Foundation;
 * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU Free Documentation License".
 */
package com.javaeye.accounting.service;

import java.util.Date;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.javaeye.accounting.dao.MaterialsMonthBatchDetailDAO;
import com.javaeye.accounting.dao.MaterialsMonthInventoryCheckDAO;
import com.javaeye.accounting.dto.MaterialsMonthBatchDetail;
import com.javaeye.accounting.dto.MaterialsMonthInventoryCheck;
import com.javaeye.accounting.dto.MaterialsMonthInventoryCheckDetail;
import com.javaeye.common.util.DateUtils;
import com.javaeye.common.util.ListUtil;
import com.javaeye.common.util.NumberUtils;
import com.javaeye.store.dao.MaterialsBatchDetailDAO;
import com.javaeye.store.dao.MaterialsChangeDetailDAO;
import com.javaeye.store.dao.MaterialsSKUDetailDAO;
import com.javaeye.store.dto.MaterialsBatchDetail;
import com.javaeye.store.dto.MaterialsCategory;
import com.javaeye.store.dto.MaterialsChangeDetail;
import com.javaeye.store.dto.MaterialsSKUDetail;

public class MaterialsMonthInventoryCheckService implements IMaterialsMonthInventoryCheckService {
	
	private MaterialsMonthInventoryCheckDAO dao;
	
	private MaterialsMonthBatchDetailDAO monthBatchDetailDao;
	
	private MaterialsSKUDetailDAO materialsSKUDetailDao;
	
	private MaterialsBatchDetailDAO materialsBatchDetailDao;
	
	private MaterialsChangeDetailDAO materialsChangeDetailDao;
	
	private Log log;
	
	public MaterialsMonthInventoryCheckService() {
		log = LogFactory.getLog(MaterialsMonthInventoryCheckService.class);
	}
	
	public void setDao(MaterialsMonthInventoryCheckDAO dao) {
		this.dao = dao;
	}

	public void setMonthBatchDetailDao(
			MaterialsMonthBatchDetailDAO monthBatchDetailDao) {
		this.monthBatchDetailDao = monthBatchDetailDao;
	}

	public void setMaterialsSKUDetailDao(MaterialsSKUDetailDAO materialsSKUDetailDao) {
		this.materialsSKUDetailDao = materialsSKUDetailDao;
	}

	public void setMaterialsBatchDetailDao(
			MaterialsBatchDetailDAO materialsBatchDetailDao) {
		this.materialsBatchDetailDao = materialsBatchDetailDao;
	}

	public void setMaterialsChangeDetailDao(
			MaterialsChangeDetailDAO materialsChangeDetailDao) {
		this.materialsChangeDetailDao = materialsChangeDetailDao;
	}

	@Override
	public List<MaterialsMonthInventoryCheck> getInventoryChecks(String year, int categoryId) {
		Calendar beginDate = Calendar.getInstance();
		beginDate.set(Calendar.YEAR, Integer.parseInt(year));
		beginDate.set(Calendar.MONTH, 0);
		beginDate.set(Calendar.DAY_OF_MONTH, 1);
		
		Calendar endDate = Calendar.getInstance();
		endDate.set(Calendar.YEAR, Integer.parseInt(year));
		endDate.set(Calendar.MONTH, 11);
		endDate.set(Calendar.DAY_OF_MONTH, 31);
		
		
		return dao.getInventoryChecks(beginDate.getTime(), endDate.getTime(), categoryId);
	}
	
	public List<MaterialsMonthBatchDetail> queryCheckDetails(
			String monthNo, List<Integer> categorys) {
		List<MaterialsMonthBatchDetail> allResult = new ArrayList<MaterialsMonthBatchDetail>();
		for (int categoryId : categorys) {
			List<MaterialsMonthBatchDetail> result = monthBatchDetailDao.getMonthInfoByChildCategory(monthNo, categoryId);
			allResult.addAll(result);
		}
		return allResult;
		
	}
	
	public void saveAddCheckDetails(String monthNo, List<Integer> categorys) {
		MaterialsMonthInventoryCheck check = new MaterialsMonthInventoryCheck();
		String checkId = ListUtil.MATERIALS_INVENTORY_CHECK_ID_PRE + DateUtils.dateToString("yyyyMM");
		int maxId = dao.getMaxInventoryCheckId(checkId) + 1;
		checkId = checkId + String.format("%04d", maxId);
		log.debug("生成的盘点编号：" + checkId);
		check.setCheckNo(checkId);
		check.setCheckDate(new Date());
		check.setMonthNo(monthNo);
		
		int count = 0;
		double amount = 0;
		double price = 0;
		float number = 0;
		for (int categoryId : categorys) {
			MaterialsCategory category = new MaterialsCategory();
			category.setId(categoryId);
			check.addCategory(category);
			
			List<MaterialsMonthBatchDetail> result = monthBatchDetailDao.getMonthInfoByChildCategory(monthNo, categoryId);
			for (MaterialsMonthBatchDetail detail : result) {
				price = detail.getPrice();
				//合格数
				number = detail.getNumber();
				if (number > 0) {
					MaterialsMonthInventoryCheckDetail checkDetail = new MaterialsMonthInventoryCheckDetail();
					checkDetail.setSkuDetail(detail.getSkuDetail());
					checkDetail.setBatchNo(detail.getBatchNo());
					checkDetail.setInventoryType(
							MaterialsMonthInventoryCheckDetail.INVENTORY_TYPE_ALLOW);
					checkDetail.setPrice(price);
					checkDetail.setNumber(number);
					checkDetail.setRealNumber(number);
					check.addDetail(checkDetail);
					amount += price * number;
					count++;
				}
				//不合格数
				number = detail.getDefectiveNumber();
				if (number > 0) {
					MaterialsMonthInventoryCheckDetail checkDetail = new MaterialsMonthInventoryCheckDetail();
					checkDetail.setSkuDetail(detail.getSkuDetail());
					checkDetail.setBatchNo(detail.getBatchNo());
					checkDetail.setInventoryType(
							MaterialsMonthInventoryCheckDetail.INVENTORY_TYPE_DEFECTIVE);
					checkDetail.setPrice(price);
					checkDetail.setNumber(number);
					checkDetail.setRealNumber(number);
					check.addDetail(checkDetail);
					amount += price * number;
					count++;
				}
			}
		}
		check.setCount(count);
		check.setAmount(NumberUtils.formatDouble(amount));
		check.setStatus(MaterialsMonthInventoryCheck.CHECK_STATUS_CREATE);
		
		dao.saveInventoryCheckInfo(check);
	}
	
	public void saveInventoryCheckResult(MaterialsMonthInventoryCheck checkInfo) {
		checkInfo.setStatus(MaterialsMonthInventoryCheck.CHECK_STATUS_CHECKED);
		dao.saveInventoryCheckInfo(checkInfo);
	}
	
	public void removeInventoryCheck(String checkNo) {
		dao.removeInventoryCheck(checkNo);
	}
	
	public MaterialsMonthInventoryCheck getInventoryCheckInfo(String checkNo) {
		MaterialsMonthInventoryCheck checkInfo = dao.getInventoryCheckInfo(checkNo);
		return checkInfo;
	}
	
	/**
	 * 根据实际盘点结果调整实际库存
	 * @param checkInfo
	 */
	public void adjustMaterialsInventory(MaterialsMonthInventoryCheck checkInfo) {
		checkInfo.setStatus(MaterialsMonthInventoryCheck.CHECK_STATUS_ADJUST);
		dao.saveInventoryCheckInfo(checkInfo);
		
		Set<MaterialsMonthInventoryCheckDetail> details = checkInfo.getDetails();
		for (MaterialsMonthInventoryCheckDetail detail : details) {
			float diffNumber = detail.getRealNumber() - detail.getNumber();
			if (diffNumber != 0) {
				int skuId = detail.getSkuDetail().getId();
				String batchNo = detail.getBatchNo();
				int inventoryType = detail.getInventoryType();
				//记录调整明细
				MaterialsChangeDetail changeDetail = new MaterialsChangeDetail();
				changeDetail.setMaterialsId(skuId);
				changeDetail.setVoucherNo(checkInfo.getCheckNo());
				if (inventoryType == MaterialsMonthInventoryCheckDetail.INVENTORY_TYPE_ALLOW) {
					if (diffNumber > 0) {
						changeDetail.setChangeType(MaterialsChangeDetail.ADJUST_INVENTORY_QUALIFIED_IN_STORE);
					} else {
						changeDetail.setChangeType(MaterialsChangeDetail.ADJUST_INVENTORY_QUALIFIED_OUT_STORE);
					}
				} else {
					if (diffNumber > 0) {
						changeDetail.setChangeType(MaterialsChangeDetail.ADJUST_INVENTORY_UNQUALIFIED_IN_STORE);
					} else {
						changeDetail.setChangeType(MaterialsChangeDetail.ADJUST_INVENTORY_UNQUALIFIED_OUT_STORE);
					}
				}
				changeDetail.setBatchNo(batchNo);
				changeDetail.setNumber(Math.abs(diffNumber));
				materialsChangeDetailDao.save(changeDetail);
				
				//调整实时库存
				MaterialsSKUDetail skuDetail = detail.getSkuDetail();
				if (inventoryType == MaterialsMonthInventoryCheckDetail.INVENTORY_TYPE_ALLOW) {
					skuDetail.setNumber(skuDetail.getNumber() + diffNumber);
				} else {
					skuDetail.setDefectiveNumber(skuDetail.getDefectiveNumber() + diffNumber);
				}
				materialsSKUDetailDao.saveMaterialsSKUDetail(skuDetail);
				
				//调整批次库存
				int category = skuDetail.getMaterials().getRootCategory().getId();
				MaterialsBatchDetail batchDetail = 
					materialsBatchDetailDao.getBatchDetail(skuId, batchNo);
				if (ListUtil.checkIsProcurementCategory(category)) {
					if (inventoryType == MaterialsMonthInventoryCheckDetail.INVENTORY_TYPE_ALLOW) {
						//合格品入库数量(原料)
						batchDetail.setInNumber(batchDetail.getInNumber() + diffNumber);
					} else {
						//不合格品入库数量(原料)
						batchDetail.setPlanNumber(batchDetail.getPlanNumber() + diffNumber);
					}
				} else {
					//合格入库数量(成品)
					batchDetail.setNumber(batchDetail.getNumber() + diffNumber);
				}
				materialsBatchDetailDao.save(batchDetail);
			}
		}
	}

}
